package edu.usm.roberge.webservice;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.rmi.RemoteException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.ServiceException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import edu.usm.roberge.model.StockQuoteData;

/**
 * Class that clients can use to interact with the web service
 */
public class StockQuoteClient {

	public static class StockQuoteClientException extends Exception {
		public StockQuoteClientException(String message) {
			super(message);
		}

		private static final long serialVersionUID = 1L;
	}
	
	public StockQuoteData getStockQuote(String symbol) throws StockQuoteClientException {
		StockQuoteLocator locator = new StockQuoteLocator();
		
		try {
			StockQuoteSoap client = locator.getStockQuoteSoap();
			String response = client.getQuote(symbol);
			return parseResponse(response);
		} catch (ServiceException e) {
			throw new StockQuoteClientException(e.getMessage());
		} catch (RemoteException e) {
			throw new StockQuoteClientException(e.getMessage());
		}
	}

	private StockQuoteData parseResponse(String response) throws StockQuoteClientException {
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = builder.parse(new ByteArrayInputStream(response.getBytes()));
			XPath xpath = XPathFactory.newInstance().newXPath();
			
			StockQuoteData quote = new StockQuoteData();
			quote.setSymbol(xpath.evaluate("/StockQuotes/Stock/Symbol/text()", document));
			quote.setLast(xpath.evaluate("/StockQuotes/Stock/Last/text()", document));
			quote.setDate(xpath.evaluate("/StockQuotes/Stock/Date/text()", document));
			quote.setTime(xpath.evaluate("/StockQuotes/Stock/Time/text()", document));
			quote.setChange(xpath.evaluate("/StockQuotes/Stock/Change/text()", document));
			quote.setOpen(xpath.evaluate("/StockQuotes/Stock/Open/text()", document));
			quote.setHigh(xpath.evaluate("/StockQuotes/Stock/High/text()", document));
			quote.setLow(xpath.evaluate("/StockQuotes/Stock/Low/text()", document));
			quote.setVolume(xpath.evaluate("/StockQuotes/Stock/Volume/text()", document));
			quote.setMktCap(xpath.evaluate("/StockQuotes/Stock/MktCap/text()", document));
			quote.setPrevClose(xpath.evaluate("/StockQuotes/Stock/PreviousClose/text()", document));
			quote.setPerChange(xpath.evaluate("/StockQuotes/Stock/PercentageChange/text()", document));
			quote.setAnnRange(xpath.evaluate("/StockQuotes/Stock/AnnRange/text()", document));
			quote.setEarns(xpath.evaluate("/StockQuotes/Stock/Earns/text()", document));
			quote.setPe(xpath.evaluate("/StockQuotes/Stock/P-E/text()", document));
			quote.setName(xpath.evaluate("/StockQuotes/Stock/Name/text()", document));
			
			return quote;
		} catch (ParserConfigurationException e) {
			throw new StockQuoteClientException("Unable to get a DocumentBuilder instance");
		} catch (SAXException e) {
			throw new StockQuoteClientException("");
		} catch (IOException e) {
			throw new StockQuoteClientException("");
		} catch (XPathExpressionException e) {
			throw new StockQuoteClientException("");
		}
	}
}
